home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 301-325 / disk_319 / cnewssrc / cnews.orig.lzh / relay / active.c next >
C/C++ Source or Header  |  1989-06-27  |  5KB  |  240 lines

  1. /*
  2.  * active file access functions
  3.  */
  4.  
  5. #include <stdio.h>
  6. #include <ctype.h>
  7. #include <sys/types.h>
  8. #include <sys/stat.h>
  9. #include "libc.h"
  10. #include "news.h"
  11. #include "config.h"
  12. #include "active.h"
  13.  
  14. /* ordinal numbers of fields */
  15. #define CURRFIELD 2        /* current article # */
  16. #define FLAGFIELD 4        /* y/n/m/x/= flag */
  17.  
  18. /* flag field values */
  19. #define FLAGOKAY 'y'        /* ordinary unmoderated group */
  20. #define FLAGBAD 'n'        /* unmoderated but locally-restricted group */
  21. #define FLAGMOD 'm'        /* moderated group */
  22. #define FLAGNEVER 'x'        /* unwanted group: don't file in this one */
  23. #define FLAGGOTO '='        /* see another group (following) instead */
  24.  
  25. /* imports */
  26. extern char *actfind();
  27. extern statust actfload(), actfsync(), actfwrnum();
  28.  
  29. /* forwards */
  30. extern char *findflag();
  31. FORWARD char *fieldfind();
  32.  
  33. /* exports */
  34. char actrelnm[] = "active";
  35.  
  36. static FILE *actfp = NULL;
  37. static struct lastngcache {
  38.     char *lnc_ng;            /* newsgroup name */
  39.     char *lnc_line;            /* matching active file line */
  40. } lnc = { NULL, NULL };
  41.  
  42. /*
  43.  * return a pointer to the active file entry for ng
  44.  * (or a pointed-to group (by ``=group'')), or 0 if no entry exists.
  45.  * since actlook is called repeatedly for the same newsgroup,
  46.  * actlook caches the last newsgroup looked-up and the result.
  47.  */
  48. STATIC char *
  49. actlook(ang)
  50. register char *ang;
  51. {
  52.     register char *ngline, *ng, *flag;
  53.     register int loopbreak = 100;
  54.  
  55.     if (lnc.lnc_ng != NULL && STREQ(lnc.lnc_ng, ang))
  56.         return lnc.lnc_line;
  57.  
  58.     if (actload() != ST_OKAY)
  59.         return NULL;
  60.     ng = strsave(ang);
  61.     while ((ngline = actfind(actfp, ng, strlen(ng))) != NULL &&
  62.         (flag = findflag(ngline)) != NULL && *flag == FLAGGOTO &&
  63.         --loopbreak > 0) {
  64.         free(ng);
  65.             ng = strsvto(flag+1, '\n');    /* follow "=ng" pointer */
  66.     }
  67.     if (loopbreak <= 0)            /* "infinite" loop broken */
  68.         ngline = NULL;
  69.  
  70.     nnfree(&lnc.lnc_ng);
  71.     lnc.lnc_ng = ng;
  72.     lnc.lnc_line = ngline;
  73.     return ngline;
  74. }
  75.  
  76. /*
  77.  * Find the active entry for ng (or a pointed-to group (by ``=group''))
  78.  * and add inc to its 2nd field (highest number).
  79.  * Return the resultant number.
  80.  */
  81. long
  82. incartnum(ng, inc)
  83. char *ng;
  84. int inc;
  85. {
  86.     char testnum[40];
  87.     register char *line = actlook(ng);
  88.     register long nextart = -1;
  89.  
  90.     if (line != NULL) {
  91.         register char *artnum, *pastartnum;
  92.  
  93.         pastartnum = artnum = fieldfind(line, CURRFIELD);
  94.         if (artnum == NULL)
  95.             return nextart;
  96.         while (isascii(*pastartnum) && isdigit(*pastartnum))
  97.             ++pastartnum;
  98.         nextart = atol(artnum) + inc;
  99.  
  100.         /* update active file article # in place, from nextart */
  101.         if (pastartnum-artnum > sizeof testnum ||
  102.             !ltozan(testnum, nextart, pastartnum-artnum) ||
  103.             !ltozan(artnum, nextart, pastartnum-artnum)) {
  104.             (void) fprintf(stderr,
  105. "%s: article number (%ld) too big for group `%s' active field of %d digits\n",
  106.                 progname, nextart, ng, pastartnum-artnum);
  107.             return -1;
  108.         }
  109.  
  110.         /* give the implementation a chance to write line to disk */
  111.         if (actfwrnum(actfp, line) != ST_OKAY) {
  112.             warning("can't update active file", "");
  113.             nextart = -1;
  114.         }
  115.     }
  116.     return nextart;
  117. }
  118.  
  119. /*
  120.  * Reload the active file cache.
  121.  */
  122. statust
  123. actload()
  124. {
  125.     register statust status = ST_OKAY;
  126.  
  127.     if (actfp == NULL &&
  128.         (actfp = fopenwclex(ctlfile(actrelnm), "r+")) == NULL)
  129.         status |= ST_DROPPED;
  130.     status |= actfload(actfp);
  131.     return status;
  132. }
  133.  
  134. /*
  135.  * Write back to disk the active file cache, if any, and flush the
  136.  * last-newsgroup-cache, since it refers to the (now invalid) active file cache
  137.  
  138.  */
  139. statust
  140. actsync()
  141. {
  142.     register statust status = ST_OKAY;
  143.  
  144.     if (actfp != NULL) {
  145.         lnc.lnc_ng = lnc.lnc_line = NULL;
  146.         status |= actfsync(actfp);
  147.         if (nfclose(actfp) == EOF || status != ST_OKAY) {
  148.             warning("error writing `%s'", ctlfile(actrelnm));
  149.             status |= ST_DROPPED;
  150.         }
  151.     }
  152.     actfp = NULL;
  153.     return status;
  154. }
  155.  
  156. /*
  157.  * Return YES iff any group in ngs (or a pointed-to group (by ``=group''))
  158.  * matches thisflag.
  159.  */
  160. boolean
  161. isflag(ngs, thisflag)
  162. register char *ngs;
  163. int thisflag;
  164. {
  165.     register char *newng, *flag, *ng;
  166.     register boolean result = NO;
  167.  
  168.     for (ng = ngs; !result && ng != NULL; ng = newng) {
  169.         newng = index(ng, NGSEP);
  170.         if (newng != NULL)
  171.             *newng = '\0';        /* restored below */
  172.  
  173.         flag = findflag(actlook(ng));
  174.         if (flag != NULL && *flag == thisflag)
  175.             result = YES;
  176.  
  177.         if (newng != NULL)
  178.             *newng++ = NGSEP;    /* point at next group */
  179.     }
  180.     return result;
  181. }
  182.  
  183. STATIC char *
  184. fieldfind(ngline, fieldno)    /* return address of field "fieldno" in ngline */
  185. register char *ngline;
  186. register int fieldno;
  187. {
  188.     register int field;
  189.  
  190.     for (field = 1; ngline != NULL && field < fieldno; ++field) {
  191.         ngline = index(ngline, ' ');
  192.         if (ngline != NULL)
  193.             ngline++;        /* point at next field */
  194.     }
  195.     return ngline;
  196. }
  197.  
  198. char *
  199. findflag(ngline)        /* return address of flag field in ngline */
  200. register char *ngline;
  201. {
  202.     return fieldfind(ngline, FLAGFIELD);
  203. }
  204.  
  205. /*
  206.  * Are any groups in ngs moderated?
  207.  */
  208. boolean
  209. moderated(ngs)
  210. register char *ngs;
  211. {
  212.     return isflag(ngs, FLAGMOD);
  213. }
  214.  
  215. /*
  216.  * Are any groups in ngs unwanted?
  217.  */
  218. boolean
  219. unwanted(ngs)
  220. register char *ngs;
  221. {
  222.     return isflag(ngs, FLAGNEVER);
  223. }
  224.  
  225. /*
  226.  * Return 0 or a malloced newsgroup name corresponding to "ong",
  227.  * but without an "=" flag in its active file entry.
  228.  * This is done by tracing the chain of "=ng" pointers (in actlook()), if any.
  229.  */
  230. char *
  231. realngname(ong)
  232. char *ong;
  233. {
  234.     register char *ngline = actlook(ong);
  235.  
  236.     if (ngline == NULL)
  237.         return NULL;            /* no such ong */
  238.     return strsvto(ngline, ' ');
  239. }
  240.